﻿using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Diagnostics;
using LowLevelGraphics;
using LowLevelGraphics.Filter;
using LowLevelGraphics.Extractors;
using LowLevelGraphics.Drawing;
//TODO: ObjectExtractor, BitmapObject,  test!!!
namespace LowLevelGraphics
{
    /// <summary>
    /// 
    /// </summary>
    public class BitmapObject : IBitmapObject, IPixelInfo
    {
        protected BitmapObject m_Parent = null;
        protected List<BitmapObject> m_aChild = null;

        protected List<Range> m_aRange = new List<Range>();
        protected List<Point> m_aPoint = new List<Point>();
        protected Rectangle m_SpannedRectangle = Rectangle.Empty;

        protected int m_nCircumference = -1;
        protected int m_nPixelCount = -1;
        protected double m_dTotalOfGrayLevel = -1.0f;

        /// <summary>
        /// Initializes a new instance of the <see cref="BitmapObject"/> class.
        /// </summary>
        public BitmapObject()
        {
        }

        //TODO: optimize this
        /// <summary>
        /// Calculates the contours.
        /// </summary>
        public virtual void CalculateContours()
        {
            CalculateContours(false);
        }

        /// <summary>
        /// Calculates the contours.
        /// </summary>
        /// <param name="_bClear">if set to <c>true</c> [_b clear].</param>
        public virtual void CalculateContours(bool _bClear)
        {
            if (_bClear)
            {
                m_aPoint.Clear();
                m_aRange.Clear();
            }
            int nPixelCount = 0;
            double dTotalOfGrayLevel = 0.0f;

            foreach (Range range in m_aRange)
            {
                m_aPoint.Add(new Point(range.StartX, range.Y));
                m_aPoint.Add(new Point(range.EndX, range.Y));

                int nLength = Math.Abs(range.EndX - range.StartX);
                nPixelCount += nLength;

                dTotalOfGrayLevel += ColorFunctions.Gray(range.Color) * nLength;
            }

            m_nPixelCount = nPixelCount;
            m_dTotalOfGrayLevel = dTotalOfGrayLevel / (double)nPixelCount;

            //Circumference is:
            //1.) first range line length - 2 pixel
            //2.) last range line length - 2 pixel 
            //3.) 2 pixel for each line 
            if (m_aRange.Count > 0)
            {
                m_nCircumference = nPixelCount + m_aRange[0].Length - 2 + m_aRange[m_aRange.Count - 1].Length - 2;
            }
        }

        /// <summary>
        /// Gets the ranges.
        /// </summary>
        /// <value>The ranges.</value>
        public List<Range> Ranges
        {
            get { return m_aRange; }
        }

        /// <summary>
        /// Gets the points.
        /// </summary>
        /// <value>The points.</value>
        public List<Point> Points
        {
            get { return m_aPoint; }
        }

        /// <summary>
        /// Gets the length of the surrounding contour (i.e. Umfang in German)
        /// </summary>
        public int Circumference
        {
            get { return m_nCircumference; }
        }

        /// <summary>
        /// Returns if this Object contains a certain range
        /// </summary>
        /// <param name="_range"></param>
        /// <returns></returns>
        public bool Contains(Range _range)
        {
            return m_aRange.Contains(_range);
        }

        /// <summary>
        /// Is this bitmapObject completely contained in another bitmapobject?!
        /// 
        /// This includes the intervall boundaries (StartX, EndX) itself.
        /// </summary>
        /// <param name="_bitmapObject"></param>
        /// <returns></returns>
        public bool IsCompletelyContainedIn(BitmapObject _bitmapObject)
        {
            bool bIsCompletelyContained = true;
            foreach (Range rangeThis in this.Ranges)
            {
                foreach (Range rangeOther in _bitmapObject.Ranges)
                {
                    bIsCompletelyContained &=
                        rangeThis.StartX >= rangeOther.StartX
                        && rangeThis.EndX <= rangeOther.EndX
                        && rangeThis.Y == rangeOther.Y;
                }
            }
            return bIsCompletelyContained;
        }

        /// <summary>
        /// Gets the spanned rectangle
        /// </summary>
        /// <value>The spanned rectangle.</value>
        public Rectangle SpannedRectangle
        {
            get { return m_SpannedRectangle; }
        }

        /// <summary>
        /// returns the pixelcount in this object
        /// </summary>
        /// <value>The pixel count.</value>
        public int PixelCount
        {
            get { return m_nPixelCount; }
        }

        public double TotalOfGrayLevel
        {
            get { return m_dTotalOfGrayLevel; }
        }
    }
}